/**
 * 定义一个接口 Product，该接口包括以下属性:
 * id:数字类型，该属性为只读属性，表示产品的唯一标识符。name:字符串类型，表示产品的名称。pice:数字类型，表示产品的价格。description:字符串类型，表示产品的描述，该属性为可选属性。
 * 要求:使用该接口创建一个对象 product1，其中 description 属性为空,
 */

interface Product {
  readonly id: number;
  name: string;
  price: number;
  description?: string;
}

const product1: Product = {
  id: 1,
  name: 'iPhone',
  price: 8999,
  // description: ''
};

/**
 * 2、使用第一题 Product 接口，声明一个Product 对象数组 类型。
 */

const products: Product[] = [
  {
    id: 1,
    name: 'iPhone',
    price: 8999,
    // description: ''
  },
  {
    id: 2,
    name: 'MacBook Pro',
    price: 14999,
    description: 'A powerful laptop'
  },
  {
    id: 3,
    name: 'iPad',
    price: 7999,
    description: 'A tablet'
  }
]

/**
 * 3. 使用类型别名定义一个函数类型 Greet,该函数接收一个参数 name,类型为 sting,且为可选参数,返回值类型为 sting。
 * 然后使用该类型声明一个问候函数 greet。
 */

type Greet = (name?: string) => string;

const greet: Greet = (name = 'world') => {
  return `Hello, ${name}!`
}

/**
 * 4、将行字面量联合类型 type Status="red"|“green";改写为常量枚举类型。
 */

const enum Status {
  red = 'red',
  green = 'green'
}

/**
 * 5、以下两个类型组合的结果是什么类型?
 * typeUser={name:string: age:number;}& {email: string; name: string;)
 */

// typeUser = {
//   name: string;
//   age: number;
//   email: string;
// }

/**
 * 6、使用泛型改写以下类型，在使用泛型声明的时候再决定 play 属性具体的类型。
 * interface Imeinv {
 * name: string
 * love: string
 * play: string | ClassB | ClassA | interfaceA }
 */

interface Imeinv<T> {
  name: string
  love: string
  play: T
}

const a: Imeinv<string> = {
  name: 'scd',
  love: 'xs',
  play: 'dc'
}

/**
 * 7、使用泛型改写以下函数加上类型控制参数 key 必须是 obj 中的键名。
 * const obj2 = {e: 'eee'.f: 'fff',g: 'ggg'.h: "hhhh'"}
 * function getObjitem(obj, key) {
 * return obj[key] }
 * getObjltem(obj2 .'e')
 */
const obj2 = { e: 'eee', f: 'fff', g: 'ggg', h: "hhhh'" }
function getObjItem<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key]
}
getObjItem(obj2, 'e')

/**
 * 8、写出内置扩展类型 Partial,Pick，Omit,Record，Readonly 的用途。
 */

// Partial --- 让属性变为可选
// Pick --- 选择某些属性，并使用交叉类型新增属性
// Omit --- 排除某些属性，并使用交叉类型新增属性
// Record --- 生成键值对
// Readonly --- 让属性变为只读

/**
 * 9、使用 declare module 给原有模块"@vue/runtime-core'扩展一个接口类型 GiobalComponents
 * (属性有 Chooselmg、ElAlert 类型都是 string)并导出。
 */
// import '@vue/runtime-core'
// declare module '@vue/runtime-core' {
//   interface GiobalComponents{
//     Chooselmg: string
//     ElAlert: string
//   }
// }

/**
 * 10、使用 CommonJS 规范 把以下变量、常量和函数导出，并写出导入语法。
 * letname='清华大学
 * constslogan='君不见，黄河之水天上来，奔流到海不复回。
 * function getTel (){
 * return'010-56253825'}
 */

// const letname:string = '清华大学'
// const constslogan:string = '君不见，黄河之水天上来，奔流到海不复回。'
// function getTel():string {
//   return '010-56253825'
// }

// module.exports = {
//   letname,
//   constslogan,
//   getTel
// }

// const {letname, constslogan, getTel} = require('./module')
// console.log(letname);
// console.log(constslogan);
// console.log(getTel);

/**
 * 11
 */
// 使用 es6 模块化导出以下代码，
// 使用分别导出方式导出name,统一导出方式导出sogan、getCities,使用默认导出导出getTel，
// 并使用一条导入语法导入，导入的时候 getCities 使用名 getC,name 使用别名 username.t5
// constname={str:'破阵子·为陈同甫赋壮词以寄之'}constslogan='醉里挑灯看剑，梦回吹角连营。
// function getTel (){
// return '010-56253825'}function getCities(){
// return['北京’'上海，深圳"，成都，武汉，西安”]}


// export const name1 = { str: '破阵子·为陈同甫赋壮词以寄之' }
// const slogan = '醉里挑灯看剑，梦回吹角连营'
// function getTel() {
//   return '010-56253825'
// }
// function getCities() {
//   return '北京,上海,深圳,成都,武汉,西安'
// }

// export {slogan,getCities} 
// export default getTel

// import getTel,{getCities as getC, name1 as username, slogan  } from "src/teacher/2.1初步体验/sc";

/**
 * 12
 */
// 使用回调函数改下以下代码，调用函数传入匿名函数，在3秒后返回“学海无涯”
// functionfun1 (func){// 提示: func =()=>{}func()
// setTimeout(() =>{
// // 这里返回学海无涯
// }, 1000);
// }

function fun1(func: (params: string) => void) {
  setTimeout(() => {
    // 这里返回学海无涯
    func('学海无涯')
  }, 3000);
}

fun1((message) => {
  console.log(message);
})

/**
 * 13、描述出以下代码调用部分的运行流程和运行结果:
 */

// 调用 fun1():

// fun1 返回一个 Promise 对象。
// 在 1 秒后（1000 毫秒），setTimeout 回调函数执行，调用 resolve，传递字符串 "范声强"。
// .then 方法:

// fun1().then(...) 在 fun1 返回的 Promise 被解决后执行回调。
// 回调函数接收到 fun1 解决的值 "范声强"，并打印它。
// 调用 fun2():

// 回调函数中调用 fun2，返回一个 Promise 对象。
// 在 1 秒后（1000 毫秒），setTimeout 回调函数执行，调用 resolve，传递字符串 "张长春"。
// 第二个 .then 方法:

// fun2().then(...) 在 fun2 返回的 Promise 被解决后执行回调。
// 回调函数接收到 fun2 解决的值 "张长春"，并打印它。

/**
 * 14、说出ts 中的类型关键字 keyof、typeof、in、instanceof、is 的作用以及使用场景。
 */

// keyof：

// 获取一个类型的所有公共属性键的联合类型。
// 用于遍历对象的所有属性。
// typeof：

// 获取变量或对象的类型。
// 用于引用变量的类型，而不是变量的值。
// in：

// 创建一个条件类型，检查属性是否存在于类型中。
// 用于基于属性存在性生成不同的类型。
// instanceof：

// 检查值是否是特定类的实例。
// 用于类型守卫或类型断言。
// is：

// 创建一个类型谓词，用于类型守卫。
// 用于在编译时检查值的类型。